package com.xjscrm.console.service.customer.group.impl;

import com.alibaba.fastjson.JSONObject;
import com.google.common.util.concurrent.RateLimiter;
import com.xjscrm.common.constant.ResponseMsg;
import com.xjscrm.common.enums.RedisCacheKeyEnum;
import com.xjscrm.common.exception.BusinessException;
import com.xjscrm.common.result.ResponseCode;
import com.xjscrm.common.utils.Math;
import com.xjscrm.common.vo.wwgroupconfig.BatchQuitGroupGap;
import com.xjscrm.common.vo.wwgroupconfig.UpdateGroupNameGap;
import com.xjscrm.common.vo.wwgroupconfig.WwGroupConfig;
import com.xjscrm.console.param.group.*;
import com.xjscrm.console.service.customer.group.WwGroupBatchService;
import com.xjscrm.console.service.customer.group.WwGroupService;
import com.xjscrm.console.vo.WwGroupVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Random;

@Service
public class WwGroupBatchServiceImpl implements WwGroupBatchService {

    @Autowired
    private WwGroupService wwGroupService;

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public void batchGroupMemberUpdateGroupName(WwGroupDto wwGroupDto) {
        if(wwGroupDto.getIds()==null||wwGroupDto.getIds().isEmpty()){
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, ResponseMsg.PARAMETER_ERROR);
        }

        if(wwGroupDto.getSelectType()==0){
            for (Long id:wwGroupDto.getIds()) {
                try {
                    wwGroupDto.setId(id);
                    wwGroupService.groupMemberUpdateGroupName(wwGroupDto);
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }

         if(wwGroupDto.getSelectType()==1){
             groupMemberUpdateGroupNameBySelect(wwGroupDto);
         }
    }

    @Async("taskExecutor")
    public void groupMemberUpdateGroupNameBySelect(WwGroupDto wwGroupDto) {
        if (wwGroupDto.getWwGroupQuery() == null) {
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, ResponseMsg.PARAMETER_ERROR);
        }
        WwGroupQuery wwGroupQuery = wwGroupDto.getWwGroupQuery();
        Long idStart = 0L;
        wwGroupQuery.setMerId(wwGroupDto.getMerId());
        wwGroupQuery.setAsc(true);
        wwGroupQuery.setCurrent(1);
        wwGroupQuery.setSize(100);
        wwGroupQuery.setOrderByField("id");
        wwGroupQuery.setIdStart(idStart);
        List<WwGroupVo> records = wwGroupService.getWwGroupList(wwGroupQuery).getRecords();

        while (records != null && !records.isEmpty()) {
            for (WwGroupVo wwGroupVo : records) {
                try {
                    if (wwGroupVo.getId().longValue() > idStart.longValue()) {
                        idStart = wwGroupVo.getId();
                    }
                    wwGroupDto.setId(wwGroupVo.getId());
                    wwGroupService.groupMemberUpdateGroupName(wwGroupDto);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            wwGroupQuery.setIdStart(idStart);
            records = wwGroupService.getWwGroupList(wwGroupQuery).getRecords();
        }
    }

    @Override
    @Async("taskExecutor")
    public void batchUpdateGroupName(BatchUpdateGroupNameDto batchUpdateGroupNameDto) {
//        if (batchUpdateGroupNameDto.getIds() == null || batchUpdateGroupNameDto.getIds().isEmpty()) {
//            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, ResponseMsg.PARAMETER_ERROR);
//        }
        if (batchUpdateGroupNameDto.getType() == null) {
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, ResponseMsg.PARAMETER_ERROR);
        }
        if (batchUpdateGroupNameDto.getType() == 1) {

            if(batchUpdateGroupNameDto.getSelectType()==0){

                RateLimiter limiter = getUpdateNameRateLimiter(batchUpdateGroupNameDto);

                for (Long id : batchUpdateGroupNameDto.getIds()) {
                    try {
                        if (limiter != null) {
                            limiter.acquire();
                        }
                        batchUpdateGroupNameDto.setId(id);
                        wwGroupService.updateGroupNameReplace(batchUpdateGroupNameDto);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }

            if(batchUpdateGroupNameDto.getSelectType()==1){
                updateGroupNameBySelect(batchUpdateGroupNameDto);
            }

        }


        if (batchUpdateGroupNameDto.getType() == 0) {
//            if (batchUpdateGroupNameDto.getBeginNumber() == null) {
//                throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, ResponseMsg.PARAMETER_ERROR);
//            }
            if(batchUpdateGroupNameDto.getSelectType()==0){

                RateLimiter limiter = getUpdateNameRateLimiter(batchUpdateGroupNameDto);

                if(batchUpdateGroupNameDto.getBeginNumber()!=null){
                    Integer beginNumber = batchUpdateGroupNameDto.getBeginNumber();
                    for (Long id : batchUpdateGroupNameDto.getIds()) {
                        try {
                            if (limiter != null) {
                                limiter.acquire();
                            }

                            batchUpdateGroupNameDto.setId(id);
                            wwGroupService.updateGroupName(batchUpdateGroupNameDto);
                            beginNumber++;
                            batchUpdateGroupNameDto.setBeginNumber(beginNumber);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }

                if(batchUpdateGroupNameDto.getBeginNumber()==null){
                    for (Long id : batchUpdateGroupNameDto.getIds()) {
                        try {
                            if (limiter != null) {
                                limiter.acquire();
                            }

                            batchUpdateGroupNameDto.setId(id);
                            wwGroupService.updateGroupName(batchUpdateGroupNameDto);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }

            }

            if(batchUpdateGroupNameDto.getSelectType()==1){
                updateGroupBySelect(batchUpdateGroupNameDto);
            }


        }

    }

    @Async("taskExecutor")
    public void updateGroupBySelect(BatchUpdateGroupNameDto batchUpdateGroupNameDto) {
        if (batchUpdateGroupNameDto.getWwGroupQuery() == null) {
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, ResponseMsg.PARAMETER_ERROR);
        }
        RateLimiter limiter = getUpdateNameRateLimiter(batchUpdateGroupNameDto);

        WwGroupQuery wwGroupQuery = batchUpdateGroupNameDto.getWwGroupQuery();
        Long idStart = 0L;
        wwGroupQuery.setMerId(batchUpdateGroupNameDto.getMerId());
        wwGroupQuery.setAsc(true);
        wwGroupQuery.setCurrent(1);
        wwGroupQuery.setSize(100);
        wwGroupQuery.setOrderByField("id");
        wwGroupQuery.setIdStart(idStart);
        if(batchUpdateGroupNameDto.getBeginNumber()==null){
            List<WwGroupVo> records = wwGroupService.getWwGroupList(wwGroupQuery).getRecords();

            while (records != null && !records.isEmpty()) {
                for (WwGroupVo wwGroupVo : records) {

                    if (limiter != null) {
                        limiter.acquire();
                    }

                    try {
                        if (wwGroupVo.getId().longValue() > idStart.longValue()) {
                            idStart = wwGroupVo.getId();
                        }
                        batchUpdateGroupNameDto.setId(wwGroupVo.getId());
                        wwGroupService.updateGroupName(batchUpdateGroupNameDto);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                wwGroupQuery.setIdStart(idStart);
                records = wwGroupService.getWwGroupList(wwGroupQuery).getRecords();
            }
        }


        if(batchUpdateGroupNameDto.getBeginNumber()!=null){
            Integer beginNumber = batchUpdateGroupNameDto.getBeginNumber();
            List<WwGroupVo> records = wwGroupService.getWwGroupList(wwGroupQuery).getRecords();

            while (records != null && !records.isEmpty()) {
                for (WwGroupVo wwGroupVo : records) {
                    try {
                        if (wwGroupVo.getId().longValue() > idStart.longValue()) {
                            idStart = wwGroupVo.getId();
                        }
                        batchUpdateGroupNameDto.setId(wwGroupVo.getId());
                        wwGroupService.updateGroupName(batchUpdateGroupNameDto);
                        beginNumber++;
                        batchUpdateGroupNameDto.setBeginNumber(beginNumber);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                wwGroupQuery.setIdStart(idStart);
                records = wwGroupService.getWwGroupList(wwGroupQuery).getRecords();
            }
        }

    }


    @Async("taskExecutor")
    public void updateGroupNameBySelect(BatchUpdateGroupNameDto batchUpdateGroupNameDto) {
        if(batchUpdateGroupNameDto.getWwGroupQuery()==null){
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, ResponseMsg.PARAMETER_ERROR);
        }
        RateLimiter limiter = getUpdateNameRateLimiter(batchUpdateGroupNameDto);

        WwGroupQuery wwGroupQuery = batchUpdateGroupNameDto.getWwGroupQuery();
        Long idStart = 0L;
        wwGroupQuery.setMerId(batchUpdateGroupNameDto.getMerId());
        wwGroupQuery.setAsc(true);
        wwGroupQuery.setCurrent(1);
        wwGroupQuery.setSize(100);
        wwGroupQuery.setOrderByField("id");
        wwGroupQuery.setIdStart(idStart);
        List<WwGroupVo> records = wwGroupService.getWwGroupList(wwGroupQuery).getRecords();

        while (records != null && !records.isEmpty()) {
            for (WwGroupVo wwGroupVo : records) {

                if (limiter != null) {
                    limiter.acquire();
                }

                try {
                    if (wwGroupVo.getId().longValue() > idStart.longValue()) {
                        idStart = wwGroupVo.getId();
                    }
                    batchUpdateGroupNameDto.setId(wwGroupVo.getId());
                    wwGroupService.updateGroupNameReplace(batchUpdateGroupNameDto);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            wwGroupQuery.setIdStart(idStart);
            records = wwGroupService.getWwGroupList(wwGroupQuery).getRecords();
        }

    }

    @Override
    public void batchdeleGroup(WwGroupDto wwGroupDto) {
        if (wwGroupDto.getIds() == null || wwGroupDto.getIds().isEmpty()) {
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, ResponseMsg.PARAMETER_ERROR);
        }

        if(wwGroupDto.getSelectType()==0){
            for (Long id:wwGroupDto.getIds()) {
                try {
                    wwGroupDto.setId(id);
                    wwGroupService.deleGroup(wwGroupDto);
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }
        if(wwGroupDto.getSelectType()==1){
            deleGroupByselect(wwGroupDto);
        }

    }

    @Async("taskExecutor")
    public void deleGroupByselect(WwGroupDto wwGroupDto) {
        if (wwGroupDto.getWwGroupQuery() == null) {
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, ResponseMsg.PARAMETER_ERROR);
        }
        WwGroupQuery wwGroupQuery = wwGroupDto.getWwGroupQuery();
        Long idStart = 0L;
        wwGroupQuery.setMerId(wwGroupDto.getMerId());
        wwGroupQuery.setAsc(true);
        wwGroupQuery.setCurrent(1);
        wwGroupQuery.setSize(100);
        wwGroupQuery.setOrderByField("id");
        wwGroupQuery.setIdStart(idStart);
        List<WwGroupVo> records = wwGroupService.getWwGroupList(wwGroupQuery).getRecords();

        while (records != null && !records.isEmpty()) {
            for (WwGroupVo wwGroupVo : records) {
                try {
                    if (wwGroupVo.getId().longValue() > idStart.longValue()) {
                        idStart = wwGroupVo.getId();
                    }
                    wwGroupDto.setId(wwGroupVo.getId());
                    wwGroupService.deleGroup(wwGroupDto);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            wwGroupQuery.setIdStart(idStart);
            records = wwGroupService.getWwGroupList(wwGroupQuery).getRecords();
        }
    }

    @Override
    @Async("taskExecutor")
    public void batchQuitWwGroup(WwGroupDto wwGroupDto) {
        if (wwGroupDto.getIds() == null || wwGroupDto.getIds().isEmpty()) {
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, ResponseMsg.PARAMETER_ERROR);
        }
        RateLimiter limiter = getQuitGroupRateLimiter(wwGroupDto);

        if(wwGroupDto.getSelectType()==0){
            for (Long id:wwGroupDto.getIds()) {

                if (limiter != null) {
                    limiter.acquire();
                }

                try {
                    wwGroupDto.setId(id);
                    wwGroupService.QuitWwGroup(wwGroupDto);
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }
        if(wwGroupDto.getSelectType()==1){
            quitWwGroupBySelect(wwGroupDto);
        }


    }

    @Async("taskExecutor")
    public void quitWwGroupBySelect(WwGroupDto wwGroupDto) {
        if (wwGroupDto.getWwGroupQuery() == null) {
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, ResponseMsg.PARAMETER_ERROR);
        }
        RateLimiter limiter = getQuitGroupRateLimiter(wwGroupDto);

        WwGroupQuery wwGroupQuery = wwGroupDto.getWwGroupQuery();
        Long idStart = 0L;
        wwGroupQuery.setMerId(wwGroupDto.getMerId());
        wwGroupQuery.setAsc(true);
        wwGroupQuery.setCurrent(1);
        wwGroupQuery.setSize(100);
        wwGroupQuery.setOrderByField("id");
        wwGroupQuery.setIdStart(idStart);
        List<WwGroupVo> records = wwGroupService.getWwGroupList(wwGroupQuery).getRecords();

        while (records != null && !records.isEmpty()) {
            for (WwGroupVo wwGroupVo : records) {

                if (limiter != null) {
                    limiter.acquire();
                }

                try {
                    if (wwGroupVo.getId().longValue() > idStart.longValue()) {
                        idStart = wwGroupVo.getId();
                    }
                    wwGroupDto.setId(wwGroupVo.getId());
                    wwGroupService.QuitWwGroup(wwGroupDto);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            wwGroupQuery.setIdStart(idStart);
            records = wwGroupService.getWwGroupList(wwGroupQuery).getRecords();
        }
    }

    @Override
    public void transferGroupAdmin(TransferGroupAdminDto transferGroupAdminDto) {
        if(transferGroupAdminDto.getGroupIds()==null||transferGroupAdminDto.getGroupIds().isEmpty()){
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, ResponseMsg.PARAMETER_ERROR);
        }
        for (Long groupId:transferGroupAdminDto.getGroupIds()) {
          try {
              transferGroupAdminDto.setGroupId(groupId);
              wwGroupService.transferGroupAdmin(transferGroupAdminDto);
          }catch (Exception e){
              e.printStackTrace();
          }
        }
    }


    @Override
    public void addGroupManager(AddGroupManagerDto addGroupManagerDto) {
        if(addGroupManagerDto.getGroupIds()==null||addGroupManagerDto.getGroupIds().isEmpty()){
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, ResponseMsg.PARAMETER_ERROR);
        }
        for (Long groupId:addGroupManagerDto.getGroupIds()) {
            try {
                addGroupManagerDto.setGroupId(groupId);
                wwGroupService.addGroupManager(addGroupManagerDto);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }


    public RateLimiter getUpdateNameRateLimiter(BatchUpdateGroupNameDto batchUpdateGroupNameDto) {
        String key = String.format(RedisCacheKeyEnum.WWGROUP_CONFIG.getKey(), batchUpdateGroupNameDto.getMerId());
        RateLimiter limiter = null;
        if (redisTemplate.hasKey(key)) {
            WwGroupConfig wwGroupConfig = JSONObject.parseObject(redisTemplate.opsForValue().get(key).toString(), WwGroupConfig.class);
            if (wwGroupConfig != null) {
                UpdateGroupNameGap updateGroupNameGap = wwGroupConfig.getUpdateGroupNameGap();
                if (updateGroupNameGap != null && updateGroupNameGap.getLow() != null && updateGroupNameGap.getUpper() != null) {
                    // 创建一个RateLimiter，每秒只发出2个令牌
                    limiter = RateLimiter.create(Math.div(1, getRandomTimeInterval(updateGroupNameGap.getLow(), updateGroupNameGap.getUpper())));
                }
            }
        }
        return limiter;
    }

    public RateLimiter getQuitGroupRateLimiter(WwGroupDto wwGroupDto) {
        String key = String.format(RedisCacheKeyEnum.WWGROUP_CONFIG.getKey(), wwGroupDto.getMerId());
        RateLimiter limiter = null;
        if (redisTemplate.hasKey(key)) {
            WwGroupConfig wwGroupConfig = JSONObject.parseObject(redisTemplate.opsForValue().get(key).toString(), WwGroupConfig.class);
            if (wwGroupConfig != null) {
                BatchQuitGroupGap batchQuitGroupGap = wwGroupConfig.getBatchQuitGroupGap();
                if (batchQuitGroupGap != null && batchQuitGroupGap.getLow() != null && batchQuitGroupGap.getUpper() != null) {
                    // 创建一个RateLimiter，每秒只发出2个令牌
                    limiter = RateLimiter.create(Math.div(1, getRandomTimeInterval(batchQuitGroupGap.getLow(), batchQuitGroupGap.getUpper())));
                }
            }
        }
        return limiter;
    }

    public Integer getRandomTimeInterval(Integer minGap, Integer maxGap) {
        Random random = new Random();
        return random.nextInt(maxGap - minGap + 1) + minGap;
    }
}
